import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Alert, Button, Flex, Form, Input, Select, Space, Spin, message } from 'antd'

import { ListColumn, ListTable } from '@visactor/react-vtable'
import * as VTable from '@visactor/vtable'
import { InputEditor } from '@visactor/vtable-editors'

import { getObjectPropertyValue, setObjectPropertyValue } from './utils'
import { getLangData, setLangData } from './api'
import { I18N_LANGUAGE } from './config'

import './App.css'

// 注册行内编辑插件
const inputEditor = new InputEditor()
VTable.register.editor('input-editor', inputEditor)

const I18n = () => {
  // form实例
  const [form] = Form.useForm()

  // table实例
  const tableRef = useRef()

  const [saveLoading, setSaveLoading] = useState(false)
  const [loading, setLoading] = useState(true)

  // 语言数据
  const [lang, setLang] = useState({})

  // 表格查询数据
  const [value, setValue] = useState({
    identifier: '',
    en: '',
  })

  // 被编辑的数据，保存后清空
  const [editorCell, setEditorCell] = useState(new Map())
  const [selectCell, setSelectCell] = useState(null)

  const [tooltipSize, setTooltipSize] = useState({
    left: -1000,
    top: -1000,
  })

  // table数据
  const [data, setData] = useState([])

  useEffect(() => {
    const unload = (event) => {
      event.preventDefault()
      event.returnValue = ''
      if (window.confirm('确定要关闭窗口吗？')) {
        // 用户点击了确定按钮，执行关闭操作
      } else {
        // 用户点击了取消按钮，取消关闭操作
      }
    }

    window.addEventListener('beforeunload', unload)
    return () => {
      window.removeEventListener('beforeunload', unload)
    }
  }, [])

  // 获取语言数据
  useEffect(() => {
    getLangData()
      .then((res) => {
        if (res.data.success && res.data.data) {
          setLang({ ...res.data.data })
        }
      })
      .finally(() => {
        setLoading(false)
      })
  }, [])

  // 默认以en的数据渲染列表
  useEffect(() => {
    const enData = handleTranslate(lang['en'])
    setData(enData)
  }, [lang])

  /**
   * * 使用递归将完整的国际化配置转换为table数据
   * @param {*} data
   * @param {string} [prefix='']
   * @returns {*}
   */
  const handleTranslate = (data, prefix = '') => {
    let ary = []
    const key = `${prefix ? prefix + '.' : ''}`
    for (const attr in data) {
      if (data[attr] && typeof data[attr] !== 'string') {
        ary = ary.concat(handleTranslate(data[attr], `${key}${attr}`))
      } else {
        // 用来获取对应语言的文案
        const langValue = Object.keys(lang).reduce((prev, item) => {
          prev[item] = getObjectPropertyValue(lang[item], `${key}${attr}`, '')
          return prev
        }, {})

        ary.push({
          key: `${key}${attr}`,
          name: `${key}${attr}`,
          ...langValue,
        })
      }
    }

    return ary
  }

  // 支持搜索标识符过滤数据
  const filterData = useMemo(() => {
    if (!value.identifier && !value.en) {
      return data
    }

    return data.filter((item) => {
      let tag = true

      if (value.identifier) {
        tag = item.key.indexOf(value.identifier) != -1
      }

      if (value.en) {
        tag = item.en.indexOf(value.en) != -1
      }

      if (value.identifier && value.en) {
        tag = item.key.indexOf(value.identifier) != -1 && item.en.indexOf(value.en) != -1
      }

      return tag
    })

    // 过滤数据
  }, [value, data])

  // 初始化注册行内编辑
  useEffect(() => {}, [])

  // 列头
  const column = useMemo(() => {
    return [
      {
        field: 'name',
        caption: '标识',
        width: 200,
      },
      ...Object.keys(I18N_LANGUAGE).map((item) => {
        if (lang && !lang[item]) {
          return {
            field: item,
            caption: I18N_LANGUAGE[item]?.label + '未获取到',
            isNull: true,
          }
        } else {
          return {
            field: item,
            caption: I18N_LANGUAGE[item]?.label,
            editor: 'input-editor',
          }
        }
      }),
    ]
  }, [lang])

  // 行内编辑回调
  useEffect(() => {
    function handleTableCellChange(value) {
      if (value.rawValue === value.changedValue) {
        return
      }
      const langType = column[value.col]?.field
      const langKey = tableRef.current.records[value.row - 1].key
      const newValue = value.changedValue
      // console.log('gxs --> % handleTableCellChange % value:\n', value)
      setObjectPropertyValue(lang[langType], langKey, newValue)
      // TODO: 这里可能会遇到性能问题，优化可以使用ref去存一下
      setLang({ ...lang })

      setEditorCell((prev) => {
        return prev.set(`${langType}-${langKey}`, value)
      })
    }

    function handleTableCellEnter(args) {}

    if (tableRef.current) {
      tableRef.current?.on('change_cell_value', handleTableCellChange)
      tableRef.current?.on('mouseenter_cell', handleTableCellEnter)
    }
    return () => {
      tableRef.current?.off('change_cell_value', handleTableCellChange)
      tableRef.current?.off('mouseenter_cell', handleTableCellEnter)
    }
  }, [filterData, column, lang])

  // 获取table实例
  const handleTableReady = (instance, isInitial) => {
    if (isInitial) {
      tableRef.current = instance
    }
  }

  // 保存语言数据
  const onSave = useCallback(() => {
    if (saveLoading) return
    setSaveLoading(true)
    setLangData({
      data: lang,
    })
      .then((res) => {
        if (res.data?.success) {
          setEditorCell((prev) => {
            return prev.clear()
          })
          message.success('保存成功')
        } else {
          message.success('保存失败')
        }
      })
      .finally(() => {
        setSaveLoading(false)
      })
  }, [lang, saveLoading])

  const hasEditorCell = (arg) => {
    const langType = column[arg.col]?.field
    const langKey = tableRef.current.records[arg.row - 1].key
    return editorCell.has(`${langType}-${langKey}`)
  }

  const getEditorCell = (arg) => {
    const langType = column[arg.col]?.field
    const langKey = tableRef.current.records[arg.row - 1].key
    return editorCell.get(`${langType}-${langKey}`)
  }

  const handleMouseEnterCell = ({ col, row, cellRange, event }) => {
    if (row <= 0) return
    if (hasEditorCell({ col, row })) {
      setSelectCell(getEditorCell({ col, row }))

      const canvasRect = event.target.getBoundingClientRect()
      setTooltipSize({
        left: cellRange.left + canvasRect.left,
        top: cellRange.bottom + canvasRect.top,
      })
    } else {
      setSelectCell(null)
      setTooltipSize({
        left: -1000,
        top: -1000,
      })
    }
  }

  return (
    <div className={'container'}>
      <Flex style={{}} justify={'space-between'} align={''}>
        <Form
          form={form}
          name='global_state'
          layout='inline'
          onFinish={(values) => {
            setValue({ ...values })
          }}>
          <Form.Item name='identifier' label='标识'>
            <Input placeholder='请输入标识' style={{ width: 300 }} allowClear />
          </Form.Item>
          <Form.Item name='en' label='英文'>
            <Input placeholder='请输入英文' style={{ width: 300 }} allowClear />
          </Form.Item>
          <Form.Item>
            <Button
              htmlType='button'
              onClick={() => {
                form.resetFields()
                setValue({
                  identifier: '',
                  en: '',
                })
              }}>
              重置
            </Button>
          </Form.Item>
          <Form.Item>
            <Button type='primary' htmlType='submit'>
              搜索
            </Button>
          </Form.Item>
        </Form>
        <Space>
          <Button type='primary' loading={saveLoading || loading} disabled={saveLoading || loading} onClick={onSave}>
            保存
          </Button>
        </Space>
      </Flex>
      <div style={{ height: 20 }}></div>
      <Alert message='编辑完成需要点击保存按钮后生效，列头红色请确认是否存在该翻译文件，列头的()中为翻译文件的名称' type='warning' showIcon closable />
      <div style={{ height: 20 }}></div>
      <div className='table'>
        <ListTable
          autoFillHeight
          autoFillWidth
          showFrozenIcon
          frozenColCount={3}
          // widthMode="adaptive"
          keyboardOptions={{
            editCellOnEnter: true,
            // https://github.com/VisActor/VTable/issues/930
            moveEditCellOnArrowKeys: false,
            selectAllOnCtrlA: false,
            copySelected: true,
            pasteValueToCell: true,
          }}
          onCell
          records={filterData}
          onReady={handleTableReady}
          onError={(error) => {
            // console.log('gxs --> % I18n % error:\n', error)
          }}
          onMouseEnterCell={handleMouseEnterCell}>
          {column.map((item) => {
            return (
              <ListColumn
                field={item.field}
                caption={item.caption}
                key={item.field}
                width={200}
                editor={item.editor}
                headerStyle={
                  item.isNull && !loading
                    ? {
                        bgColor: '#ff4d4f',
                        color: '#fff',
                      }
                    : {}
                }
                style={{
                  bgColor(arg) {
                    if (hasEditorCell(arg)) {
                      return '#ffaa00'
                    }
                    return '#fff'
                  },
                }}
              />
            )
          })}
        </ListTable>
        {selectCell && (
          <div
            style={{
              width: 300,
              height: 80,
              position: 'fixed',
              left: tooltipSize.left,
              top: tooltipSize.top,
            }}>
            <Alert message={selectCell.changedValue} description={`修改前：${selectCell.rawValue || '无内容'}`} type='warning' />
          </div>
        )}
        <Spin spinning={loading}></Spin>
      </div>
    </div>
  )
}

export default I18n
